package com.seguriapp.entitieslist.gwt.client.activity;

import java.util.List;

import net.customware.gwt.dispatch.client.DispatchAsync;

import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.seguriapp.common.gwt.client.AbstractSeguriAppActivity;
import com.seguriapp.common.gwt.client.AbstractSeguriAppPlace;
import com.seguriapp.common.gwt.client.SeguriAppCallback;
import com.seguriapp.common.gwt.client.SeguriAppClientSession;
import com.seguriapp.common.gwt.client.SeguriAppDisplay;
import com.seguriapp.common.gwt.client.pagination.PageChangedEvent;
import com.seguriapp.common.gwt.client.pagination.PageChangedEventHandler;
import com.seguriapp.common.gwt.client.pagination.SearchPagination;
import com.seguriapp.common.gwt.client.pagination.SearchPaginationPresenter;
import com.seguriapp.entities.District;
import com.seguriapp.entities.SeguriAppEntity;
import com.seguriapp.entities.SeguriAppEntityType;
import com.seguriapp.entitieslist.gwt.shared.GetDistrictsListAction;
import com.seguriapp.entitieslist.gwt.shared.GetDistrictsListResult;
import com.seguriapp.entitieslist.gwt.shared.GetEntitiesListAction;
import com.seguriapp.entitieslist.gwt.shared.GetEntitiesListResult;
import com.seguriapp.entitieslist.gwt.shared.GetEntityTypesAction;
import com.seguriapp.entitieslist.gwt.shared.GetEntityTypesResult;

public class EntitiesListActivity extends AbstractSeguriAppActivity {

  private final Display display;
  private long page;
  private long entityTypeId;
  private List<Long> districtsList;
  private List<SeguriAppEntity> entitiessList;
  private boolean ascending;
  private String columnSort;
  private int zoomValue = 13;
  private boolean getUserLocation;

  public EntitiesListActivity(final DispatchAsync dispatchAsync, final EventBus eventBus, final PlaceController placeController,
      final Display display, final AbstractSeguriAppPlace place, final SeguriAppClientSession clientSession) {
    super(dispatchAsync, eventBus, placeController, place, clientSession);
    display.setPresenter(this);
    this.display = display;
  }

  public void setPage(final long page) {
    this.page = page;
  }

  public void setEntityTypeId(final long entityTypeId) {
    this.entityTypeId = entityTypeId;
  }

  public void setDistrictsList(final List<Long> districtsList) {
    this.districtsList = districtsList;
  }

  public void setAscending(final boolean ascending) {
    this.ascending = ascending;
  }

  public void setColumnSort(final String columnSort) {
    this.columnSort = columnSort;
  }

  @Override
  protected void onStart(final AcceptsOneWidget widget, final EventBus eventBus) {
    widget.setWidget(display.asWidget());
    setPage(FIRST_PAGE);
    initializeSearchFilters();
    getUserLocation = true;
  }

  private void initializeSearchFilters() {
    getEntityTypesListFromServer();
    getDistrictListFromServer();
    new SearchPaginationPresenter(eventBus, display.getPagination()).start();
    eventBus.addHandler(PageChangedEvent.TYPE, new PageChangedEventHandler() {

      public void onPageChanged(PageChangedEvent event) {
        setPage(event.getPage());
        updateEntitiesList();
      }
    });
  }

  private void getEntityTypesListFromServer() {
    dispatchAsync.execute(new GetEntityTypesAction(), new SeguriAppCallback<GetEntityTypesResult>() {

      public void onSuccess(final GetEntityTypesResult result) {
        display.setEntityTypesFilter(result.getEntityTypesList());
        if (result.getEntityTypesList() != null && !result.getEntityTypesList().isEmpty()) {
          setEntityTypeId(result.getEntityTypesList().get(0).getId());
        }
      }

      public void onFailure(Throwable e) {
        display.setEntityTypesFilter(null);
      }
    });
  }

  private void getDistrictListFromServer() {
    dispatchAsync.execute(new GetDistrictsListAction(), new SeguriAppCallback<GetDistrictsListResult>() {

      public void onSuccess(final GetDistrictsListResult result) {
        display.setDistrictsListFilter(result.getDistrictsList());
      }

      public void onFailure(Throwable e) {
        display.setDistrictsListFilter(null);
      }
    });
  }

  private void updateEntitiesList() {
    final GetEntitiesListAction action = new GetEntitiesListAction();
    action.setPage(page);
    action.setEntityTypeId(entityTypeId);
    action.setDistrictsList(districtsList);
    action.setAscending(ascending);
    action.setColumnSort(columnSort);
    dispatchAsync.execute(action, new SeguriAppCallback<GetEntitiesListResult>() {

      public void onSuccess(final GetEntitiesListResult result) {
        entitiessList = result.getEntitiesList();
        if (entitiessList != null && !entitiessList.isEmpty()) {
          display.setGridData(entitiessList);
          display.setPagination(result.getCurrentPage(), result.getTotalPages(), result.getMaxPages());
          display.setMapData(entitiessList, result.getDefaultLatitude(), result.getDefaultLongitude(), zoomValue, getUserLocation);
          getUserLocation = false;
        } else {
          display.showNoDataMessage();
        }
      }

      public void onFailure(final Throwable e) {
        Window.alert("Error: " + e.getMessage());
      }
    });

  }

  public void updateEntitiesData(final List<Long> districtsList, final Long entityTypeId) {
    setEntityTypeId(entityTypeId);
    setDistrictsList(districtsList);
    updateEntitiesList();
  }

  public interface Display extends SeguriAppDisplay {

    void setPresenter(EntitiesListActivity presenter);

    void setMapData(List<SeguriAppEntity> entitiessList, double latitude, double longitude, int zoomValue, boolean getUserLocation);

    void setDistrictsListFilter(List<District> districtsList);

    void setEntityTypesFilter(List<SeguriAppEntityType> entityTypesList);

    void setGridData(List<SeguriAppEntity> entitiessList);

    void setPagination(long currentPage, long totalPages, long maxPages);

    void showNoDataMessage();

    SearchPagination getPagination();
  }

}
